# 命名空间和作用域

# 命名空间：存放变量名的地方，是对栈区的划分
# 1.内置命名空间
# 存放的名字：存放python解释器内置的名字
# 存活周期：python解释器启动产生，关闭则销毁
print(print)


# 2.全局命名空间
# 存放的名字：不是内置的，也不是函数内定义的名字就是全局的
# 存活周期：python文件运行则产生，运行结束则销毁


# 3.局部命名空间
# 存放的名字：调用函数时函数内产生的名字
# 存活周期：调用函数时，调用完毕则销毁

# 命名空间加载顺序：内置命名空间>全局命名空间>局部命名空间
# 命名空间查找顺序：从当前所在位置开始，向上级空间查找
# 命名空间销毁顺序：局部命名空间>全局命名空间>内置命名空间

# 例1
def func1():
    print(x)


x = 111
func1()

# 例2-1 名称空间嵌套关系是在函数定义的阶段确定好的，与调用位置无关
a = 1


def func2():
    print(a)


def func3():
    a = 2
    func2()


# 例2-2 定义阶段依然从x=2开始查找，调用阶段报错z还未定义  说明 函数的名称查找顺序是以定义阶段为准的
z = 1


def func3():
    print(z)
    z = 2


# func3() # 调用报错

# 全局作用域：名称全局生效-内置命名空间 全局命名空间
# 局部作用域：名称函数内生效-局部名称空间

# 局部修改全局变量（不可变类型） global
aa = 1


def func4():
    global aa
    aa = 2


func4()
print(aa)

# 函数内修改上层函数（不包括全局作用域，如果上层函数中没有会报错）还是变量（不可变类型） nonlocal
bb = 2


def func5():
    bb = 3

    def func6():
        nonlocal bb
        bb = 4

    func6()
    print("func5的bb =", bb)


func5()




